﻿#include<iostream>
#include<functional>
#include<string>
using namespace std;
struct Date
{
	int _year;
	int _month;
	int _day;
	Date(int year = 1, int month = 1, int day = 1)
		:_year(year)
		, _month(month)
		, _day(day)
	{
	}
	~Date()
	{
		cout << "~Date()" << endl;
	}
};



namespace bit
{
	template<class T>
	class shared_ptr
	{
	public:
		//构造
		shared_ptr( T* ptr = nullptr)
			:_ptr(ptr)
			,_pcount(new int(1))
		{ }
		//有删除器的构造
		template<class D>
		shared_ptr( T* ptr,D del)
			: _ptr(ptr)
			, _pcount(new int(1))
			,_del(del)
		{ }
		//拷贝构造
		shared_ptr(const shared_ptr& date)
			:_ptr(date._ptr)
			,_pcount(date._pcount)
			,_del(date._del)
		{
			(*_pcount)++;
		}

		void rese()
		{
			if (--(*_pcount) == 0)
			{
				delete _ptr;
				delete _pcount;
				_ptr = nullptr;
				_pcount = nullptr;
			}
		}

		~shared_ptr()
		{
			rese();
		}

		shared_ptr<T>& operator=(const shared_ptr<T>& shar)
		{
			if (_ptr != shar._ptr)
			{
				rese();//释放sp1的资源，不然会内存泄露
				_ptr = shar._ptr;
				_pcount = shar._pcount;
				_del = shar._del;
				(*_pcount)++;
			}
			return *this;
		}

		T& operator*()
		{
			return *_ptr;
		}
		T* operator->()
		{
			return _ptr;
		}
	private:
		T* _ptr;
		int* _pcount;
		function<void(T*)> _del = [](T* ptr) { delete ptr; };
	};

	// 需要注意的是我们这⾥实现的shared_ptr和weak_ptr都是以最简洁的⽅式实现的， 
	// 只能满⾜基本的功能，这⾥的weak_ptr lock等功能是⽆法实现的，想要实现就要 
	// 把shared_ptr和weak_ptr⼀起改了，把引⽤计数拿出来放到⼀个单独类型，shared_ptr 
	// 和weak_ptr都要存储指向这个类的对象才能实现，有兴趣可以去翻翻源代码 
	template<class T>
	class weak_ptr
	{
	public:
		// 无参构造函数
		// 当创建一个 weak_ptr 对象而不提供任何参数时，会调用此构造函数
		// 它将内部的指针 _ptr 初始化为 nullptr
		weak_ptr()
		{
		}
		// 通过调用 shared_ptr 的 get() 方法获取其内部管理的原始指针，并将其赋值给 _ptr
		weak_ptr(const shared_ptr<T>& sp)
			:_ptr(sp.get())
		{
		}
		weak_ptr<T>& operator=(const shared_ptr<T>& sp)
		{
			_ptr = sp.get();
			return *this;
		}
	private:
		T* _ptr = nullptr;
	};

}


//int main()
//{
//	bit::shared_ptr<Date> sp1(new Date);
//	// ⽀持拷⻉ 
//	bit::shared_ptr<Date> sp2(sp1);
//
//	bit::shared_ptr<Date> sp3(new Date(1014, 3, 3));
//
//	cout << sp1->_day << endl;
//
//	//自己给自己赋值
//	sp3 = sp3;
//	sp1 = sp2;
//
//	sp1 = sp3;
//	//sp2 = sp3;
//
//	return 0;
//}

//struct ListNode
//{
//	int _data;
//	std::shared_ptr<ListNode> _next;
//	std::shared_ptr<ListNode> _prev;
//
//	// 这⾥改成weak_ptr，当n1->_next = n2;绑定shared_ptr时 
//	// 不增加n2的引⽤计数，不参与资源释放的管理，就不会形成循环引⽤了 
//	/*std::weak_ptr<ListNode> _next;
//	std::weak_ptr<ListNode> _prev;*/
//	~ListNode()
//	{
//		cout << "~ListNode()" << endl;
//	}
//};
//int main()
//{
//	// 循环引⽤ -- 内存泄露 
//	std::shared_ptr<ListNode> n1(new ListNode);
//	std::shared_ptr<ListNode> n2(new ListNode);
//	cout << n1.use_count() << endl;
//	cout << n2.use_count() << endl;
//	n1->_next = n2;
//	n2->_prev = n1;
//	cout << n1.use_count() << endl;
//	cout << n2.use_count() << endl;
//
//	// weak_ptr不⽀持管理资源，不⽀持RAII 
//	// weak_ptr是专⻔绑定shared_ptr，不增加他的引⽤计数，作为⼀些场景的辅助管理 
//	//std::weak_ptr<ListNode> wp(new ListNode);
//	return 0;
//}

int main()
{
	std::shared_ptr<string> sp1(new string("111111"));
	std::shared_ptr<string> sp2(sp1);
	std::weak_ptr<string> wp = sp1;
	cout << wp.expired() << endl;
	cout << wp.use_count() << endl;

	// sp1和sp2都指向了其他资源，则weak_ptr就过期了
	sp1 = make_shared<string>("222222");
	cout << wp.expired() << endl;
	cout << wp.use_count() << endl;
	sp2 = make_shared<string>("333333");
	cout << wp.expired() << endl;
	cout << wp.use_count() << endl;
	wp = sp1;

	std::shared_ptr<string> sp3 = wp.lock();
	auto sp4 = wp.lock();
	cout << wp.expired() << endl;
	cout << wp.use_count() << endl;
	*sp3 += "###";
	cout << *sp1 << endl;
	return 0;
}